// Copyright (c) 2007-2009 Simon Fell
//
// Permission is hereby granted, free of charge, to any person obtaining a 
// copy of this software and associated documentation files (the "Software"), 
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the 
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included 
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
// THE SOFTWARE.
//

#import "File.h"
#import "Folder.h"
#import "zkSforceClient.h"
#import "zkQueryResult.h"
#import "zkSObject.h"
#import "NSString-Base64Extensions.h"
#import "Mru.h"

@implementation File

+(NSString *)makeName:(NSString *)n type:(NSString *)t {
	if ([t length] == 0) return n;	// no type
	if ([n hasSuffix:t]) return n;	// name already ends with the type
	return [NSString stringWithFormat:@"%@.%@", n, t];	// glue the 2 together
}

-(void)dealloc {
	[folder release];
	[super dealloc];
}

- (id)initWithName:(NSString *)n type:(NSString *)type id:(NSString *)id modstamp:(NSDate *)ms created:(NSDate *)c length:(long)len folder:(Folder *)f {
	self = [super initWithName:[File makeName:n type:type] id:id modstamp:ms created:c];
	NSMutableDictionary *atts = [NSMutableDictionary dictionary];
	[atts setObject:NSFileTypeRegular forKey:NSFileType];
	[atts setObject:[NSNumber numberWithInt:0500] forKey:NSFilePosixPermissions];
	[atts setObject:systemModstamp forKey:NSFileModificationDate];
	[atts setObject:createdDate forKey:NSFileCreationDate];
	[atts setObject:[NSNumber numberWithLongLong:len] forKey:NSFileSize];
	attributes = [atts retain];
	folder = [f retain];
	return self;
}

- (NSString *)bodyFieldName {
	return @"Body";
}

- (NSString *)entityName {
	return @"Document";
}

- (NSString *)selectBodyQuery {
	return [NSString stringWithFormat:@"select %@ from %@ where id='%@'", [self bodyFieldName], [self entityName], sfdcId];
}


- (NSString *)systemModstampQuery {
	return [NSString stringWithFormat:@"select SystemModstamp from %@ where id='%@'", [self entityName], sfdcId];
}

- (NSData *)retrieveBody {
	ZKQueryResult *qr = [folder query:[self selectBodyQuery]];
	if ([qr size] == 0) {
		[folder clearCache];
		return nil;
	}
	NSString *b64Body = [[[qr records] objectAtIndex:0] fieldValue:[self bodyFieldName]];
	return [b64Body decodeBase64WithNewlines:NO];
}

- (BOOL)itemHasChanged {
	ZKQueryResult *qr = [folder query:[self systemModstampQuery]];
	if ([qr size] == 0) {
		[folder clearCache];
		return YES;
	}
	ZKSObject *r = [[qr records] objectAtIndex:0];
	NSCalendarDate *sm = [r dateValue:@"SystemModstamp"];
	BOOL changed = [sm timeIntervalSinceReferenceDate] > [systemModstamp timeIntervalSinceReferenceDate];
	return changed;
}

- (NSData *)fileBodyUsingMru:(Mru *)dataMru {
	NSData *body = nil;
	MruItem *cacheItem = [dataMru mruItemForKey:sfdcId];
	if (cacheItem != nil) {
		body = [cacheItem item];
		if ([cacheItem isExpired]) {
			if ([self itemHasChanged]) {
				body = nil;
			} else {
				[cacheItem resetExpiry];
			}
		}
	}
	if (body == nil) {
		body = [self retrieveBody];
		if (body != nil)
			[dataMru setObject:body forKey:sfdcId];
	}
	return body;
}

@end 

@implementation ContentFile

- (NSString *)entityName {
	return @"ContentVersion";
}

- (NSString *)bodyFieldName {
	return @"VersionData";
}

@end